Conversation
theomonnom
commented
Feb 10, 2026
There was a problem hiding this comment.
🔴 process_reverse_stream checks wrong response field, silently ignoring errors
In process_reverse_stream, the error check on line 93 reads resp.apm_process_stream.error instead of resp.apm_process_reverse_stream.error. This means any error returned by the FFI reverse-stream processing call is silently ignored.
Root Cause and Impact
The method sends a request via req.apm_process_reverse_stream but checks the response on the wrong oneof field resp.apm_process_stream.error (copy-paste from process_stream). Since protobuf oneofs default to empty/falsy when the wrong field is accessed, resp.apm_process_stream.error will always be empty after an apm_process_reverse_stream request, so the RuntimeError is never raised even when the FFI call fails.
Compare with the correct check in process_stream at apm.py:65-66:
if resp.apm_process_stream.error:
raise RuntimeError(resp.apm_process_stream.error)The process_reverse_stream method at apm.py:93-94 should mirror this but for the reverse stream:
if resp.apm_process_reverse_stream.error: # NOT apm_process_stream
raise RuntimeError(resp.apm_process_reverse_stream.error)Impact: Errors during reverse stream processing (used for echo cancellation) are silently swallowed, making it very difficult to diagnose audio processing failures in full-duplex setups.
(Refers to lines 93-94)
Was this helpful? React with 👍 or 👎 to provide feedback.
| if isinstance(data, memoryview): | ||
| if not data.contiguous: | ||
| raise ValueError("memoryview must be contiguous") | ||
| if data.nbytes != len(data.obj): # type: ignore[arg-type] |
There was a problem hiding this comment.
🟡 _buffer_supported_or_raise incorrectly rejects valid non-sliced memoryviews backed by non-byte-sized element types
The sliced-memoryview check at line 53 compares data.nbytes (always in bytes) with len(data.obj) (element count for non-byte buffer types). This causes valid, non-sliced memoryviews backed by objects like array.array, ctypes arrays, or numpy arrays to be incorrectly rejected.
Root Cause and Impact
For bytes and bytearray, len() returns byte count, so the check works. But for other buffer-exporting objects, len() returns element count:
array.array('h', range(10)):len()= 10, butmemoryview(...).nbytes= 20numpy.zeros(10, dtype=np.int16):len()= 10, butmemoryview(...).nbytes= 20- ctypes
(c_int16 * 10)():len()= 10, butmemoryview(...).nbytes= 20
When a user passes memoryview(array.array('h', samples)) or memoryview(numpy_int16_array) as the data argument to AudioFrame() or VideoFrame(), _buffer_supported_or_raise raises ValueError("sliced memoryviews are not supported") even though the memoryview is perfectly valid and non-sliced.
Impact: Users passing memoryviews of non-byte-element buffer objects (common with numpy or array.array workflows) will get a spurious ValueError.
| if data.nbytes != len(data.obj): # type: ignore[arg-type] | |
| if data.nbytes != memoryview(data.obj).nbytes: | |
Was this helpful? React with 👍 or 👎 to provide feedback.